home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MacHack 2000
/
MacHack 2000.toast
/
pc
/
The Hacks
/
Softshoe
/
Lisa's Mac Parts
/
Files
/
Locations
/
FileLocation.cp
< prev
next >
Wrap
Text File
|
2000-06-23
|
11KB
|
482 lines
// FileLocation.cp
#ifndef FileLocation_h
#include "FileLocation.h"
#endif
#ifndef PString_h
#include "PString.h"
#endif
#ifndef Str_h
#include "Str.h"
#endif
#ifndef ProcessInfo_h
#include "ProcessInfo.h"
#endif
#ifndef FileNotFoundError_h
#include "FileNotFoundError.h"
#endif
#ifndef DirectoryNotFoundError_h
#include "DirectoryNotFoundError.h"
#endif
#ifndef DuplicateFileError_h
#include "DuplicateFileError.h"
#endif
#ifndef DirectoryFullError_h
#include "DirectoryFullError.h"
#endif
#ifndef DiskFullError_h
#include "DiskFullError.h"
#endif
#ifndef HardwareVolumeLockError_h
#include "HardwareVolumeLockError.h"
#endif
#ifndef SoftwareVolumeLockError_h
#include "SoftwareVolumeLockError.h"
#endif
#ifndef FileLockError_h
#include "FileLockError.h"
#endif
#ifndef FileBusyError_h
#include "FileBusyError.h"
#endif
#ifndef FilePermissionError_h
#include "FilePermissionError.h"
#endif
#ifndef CatInfo_h
#include "CatInfo.h"
#endif
#ifndef BadFileNameError_h
#include "BadFileNameError.h"
#endif
#ifndef NotAFileError_h
#include "NotAFileError.h"
#endif
#ifndef NotADirectoryError_h
#include "NotADirectoryError.h"
#endif
#include <NumberFormatting.h>
#include <StringCompare.h>
FileLocation::FileLocation()
{
vRefNum = 0;
parID = 0;
name[0] = 0;
}
FileLocation::FileLocation( Directory directory,
ConstPString theName )
{
name[0] = 0;
SetParent( directory );
SetName( theName );
}
FileLocation::FileLocation( Directory directory )
{
name[0] = 0;
CatInfo info( directory );
*this = info.Location();
}
void FileLocation::Set( Directory directory,
ConstPString theName )
{
SetParent( directory );
SetName( theName );
}
void FileLocation::operator=( Directory directory )
{
CatInfo info( directory );
*this = info.Location();
}
void FileLocation::SetName( ConstPString newName )
{
PString( Data( name, sizeof(name) ) ) = newName;
}
void FileLocation::SetName( ConstPString base, uint32 number )
{
String31 newName;
String255 numeral;
NumToString( number, numeral );
if ( base.Length() + numeral.Length() + 1 <= 31 )
{
newName.SetLength( base.Length() + numeral.Length() + 1 );
newName.Head( base.Length() ) << base;
newName[ base.Length() ] = ' ';
newName.Tail( base.Length() + 1 ) << numeral;
}
else if ( base.Length() + numeral.Length() <= 31 )
{
newName.SetLength( base.Length() + numeral.Length() );
newName.Head( base.Length() ) << base;
newName.Tail( base.Length() ) << numeral;
}
else
{
uint32 baseAmount = 31 - numeral.Length() - 1;
static const uint8 elipsis = 0xc9;
newName.SetLength( 31 );
newName.Head( baseAmount ) << base;
newName[ baseAmount ] = elipsis;
newName.Tail( baseAmount + 1 ) << numeral;
}
SetName( newName );
}
Directory FileLocation::AsDirectory() const
{
return CatInfo( *this ).AsDirectory();
}
bool FileLocation::NameIsValid() const
{
ConstPString name( this->name );
if ( name.Length() == 0 )
return false;
if ( name.Length() > 31 )
return false;
if ( name[0] == '.' )
return false;
for ( uint32 i = 0; i < name.Length(); i++ )
if ( name[i] == ':' )
return false;
return true;
}
void FileLocation::SetToValidName( ConstPString start )
{
SetName( start );
SetToValidName();
}
void FileLocation::SetToValidName()
{
PString name( Data( this->name, sizeof(this->name) ) );
static const uint8 bullet = 0xA5;
if ( name.Length() == 0 )
{
name.SetLength( 1 );
name[0] = bullet;
}
if ( name.Length() > 31 )
name.SetLength( 31 );
if ( name[0] == '.' )
name[0] = bullet;
for ( uint32 i = 0; i < name.Length(); i++ )
if ( name[i] == ':' )
name[i] = '/';
Assert( NameIsValid() );
}
bool operator==( const FileLocation& a, const FileLocation& b )
{
return a.vRefNum == b.vRefNum
&& a.parID == b.parID
&& EqualString( a.name, b.name, false, true );
}
void FileLocation::ThrowError( OSErr error )
{
if ( error == noErr )
return;
switch ( error )
{
case fnfErr: throw FileNotFoundError( error );
case dirNFErr: throw DirectoryNotFoundError( error );
case dupFNErr: throw DuplicateFileError( error );
case dirFulErr: throw DirectoryFullError( error );
case dskFulErr: throw DiskFullError( error );
case wPrErr: throw HardwareVolumeLockError( error );
case vLckdErr: throw SoftwareVolumeLockError( error );
case fLckdErr: throw FileLockError( error );
case fBsyErr: throw FileBusyError( error );
case afpAccessDenied: throw FilePermissionError( error );
case bdNamErr: throw BadFileNameError( error );
}
throw FileError( error );
}
bool FileLocation::Exists() const
{
Assert( NameIsValid() );
String255 localName( name );
CInfoPBRec info;
info.hFileInfo.ioCompletion = 0;
info.hFileInfo.ioVRefNum = vRefNum;
info.hFileInfo.ioDirID = parID;
info.hFileInfo.ioNamePtr = localName;
info.hFileInfo.ioFVersNum = 0;
info.hFileInfo.ioFDirIndex = 0;
OSErr error = PBGetCatInfoSync( &info );
if ( error != noErr && error != fnfErr )
ThrowError( error );
return error == noErr;
}
void FileLocation::FindUnusedName()
{
if ( !Exists() )
return;
String31 baseName( name );
uint32 number = 1;
do
{
Assert( number < maxuint32 );
SetName( baseName, ++number );
}
while ( Exists() );
}
void FileLocation::Up()
{
Assert( !IsRoot() );
if ( IsRoot() )
ThrowError( dirNFErr );
CatInfo info( Parent() );
*this = info.Location();
}
void FileLocation::Down( ConstPString child )
{
SetParent( AsDirectory() );
SetName( child );
}
void FileLocation::Sideways( ConstPString sibling )
{
SetName( sibling );
}
FileLocation FileLocation::Child( ConstPString child ) const
{
return FileLocation( AsDirectory(), child );
}
FileLocation FileLocation::Sibling( ConstPString sibling ) const
{
return FileLocation( Parent(), sibling );
}
DirectoryID FileLocation::GetDirectoryID() const
{
CatInfo info( *this );
Assert( info.IsDirectory() );
if ( !info.IsDirectory() )
ThrowError( afpObjectTypeErr );
return info.Directory().ID();
}
FileID FileLocation::GetFileID() const
{
CatInfo info( *this );
Assert( !info.IsDirectory() );
if ( info.IsDirectory() )
ThrowError( notAFileErr );
return info.File().ID();
}
void CreateFile( const FileLocation& location,
FileType type,
FileSignature signature,
ScriptID script )
{
Assert( location.NameIsValid() );
FileLocation::ThrowError( FSpCreate( &location,
signature.Signature(),
type.Type(),
script.ID() ) );
}
void CreateFile( const FileLocation& location,
FileType type,
ScriptID script )
{
CreateFile( location,
type,
ProcessInfo::Application().Signature(),
script );
}
Directory CreateDirectory( const FileLocation& location, ScriptID script )
{
Assert( location.NameIsValid() );
int32 directory;
FileLocation::ThrowError( FSpDirCreate( &location, script.ID(), &directory ) );
return Directory( location.Volume(), DirectoryID( directory ) );
}
void DeleteFile( const FileLocation& file )
{
Assert( file.NameIsValid() );
DeleteFile( CatInfo( file ) );
}
void DeleteDirectory( const FileLocation& directory )
{
Assert( directory.NameIsValid() );
DeleteDirectory( CatInfo( directory ) );
}
void LockFile( const FileLocation& file )
{
Assert( file.NameIsValid() );
FileLocation::ThrowError( FSpSetFLock( &file ) );
}
void UnlockFile( const FileLocation& file )
{
Assert( file.NameIsValid() );
FileLocation::ThrowError( FSpRstFLock( &file ) );
}
void MoveFile( const FileLocation& source, const FileLocation& destination )
{
Assert( source.Volume() == destination.Volume() );
Assert( source != destination );
Assert( source.NameIsValid() );
Assert( destination.NameIsValid() );
MoveFile( CatInfo( source ), destination );
}
void SwapFiles( const FileLocation& left, const FileLocation& right )
{
Assert( left.Volume() == right.Volume() );
Assert( left != right );
Assert( left.NameIsValid() );
Assert( right.NameIsValid() );
FileLocation::ThrowError( FSpExchangeFiles( &left, &right ) );
}
void DeleteDirectory( const CatInfo& source )
{
if ( !source.IsDirectory() )
throw NotADirectoryError( afpObjectTypeErr );
FileLocation::ThrowError( FSpDelete( &source.Location() ) );
}
void DeleteFile( const CatInfo& source )
{
if ( !source.IsFile() )
throw NotAFileError( notAFileErr );
FileLocation::ThrowError( FSpDelete( &source.Location() ) );
}
void MoveFile( const CatInfo& source, const FileLocation& destination )
{
Assert( source.Location().Volume() == destination.Volume() );
Assert( source.Location() != destination );
Assert( source.Location().NameIsValid() );
Assert( destination.NameIsValid() );
if ( !source.IsFile() )
throw NotAFileError( notAFileErr );
if ( destination.ParentID() == source.Location().ParentID() )
FileLocation::ThrowError( FSpRename( &source.Location(), destination.Name() ) );
else
FileLocation::ThrowError( FSpCatMove( &source.Location(), &destination ) );
}
void ForceDirectoryExistence( const FileLocation& destination )
{
CatInfo info;
bool exists = info.TryToGet( destination );
if ( exists && info.IsDirectory() )
return;
if ( exists )
ForceNonexistence( destination );
CreateDirectory( destination );
}
void ForceNonexistence( const FileLocation& source )
{
Assert( source.NameIsValid() );
OSErr error = FSpDelete( &source );
if ( error != noErr && error != fnfErr )
FileLocation::ThrowError( error );
}
void ForceMoveFile( const FileLocation& source, const FileLocation& destination )
{
CatInfo sourceInfo( source );
// Check for these errors before deleting:
if ( !sourceInfo.IsFile() )
throw NotAFileError( notAFileErr );
ForceNonexistence( destination );
MoveFile( sourceInfo, destination );
}
void ForceCopyFile( const FileLocation& source, const FileLocation& destination )
{
CatInfo sourceInfo( source );
// Check for these errors before deleting:
if ( !sourceInfo.IsFile() )
throw NotAFileError( notAFileErr );
ForceNonexistence( destination );
CopyFile( sourceInfo, destination );
}
void DeleteRecursively( const FileLocation& top )
{
CatInfo info( top );
while ( true )
{
while ( info.IsDirectory() && info.TryToGet( info.AsDirectory(), 1 ) )
;
FileLocation::ThrowError( FSpDelete( &info.Location() ) );
if ( info.Location() == top )
return;
info.Up();
}
}